/*
 * can.c
 *
 *  Created on: 2020年6月21日
 *      Author: armwind
 */
#include "can.h"
#include "stm32f0xx.h"
#include "common.h"

char *can_err_str[8] = {
        "No Error",
        "Stuff Error",
        "Form Error",
        "Acknowledgment Error",
        "Bit recessive Error",
        "Bit dominant Error",
        "CRC Error",
        "Set by software"
};

/**
  * @brief  基于48M系统时钟及选择波特率，计算CAN时钟的预分频系数
  * @param  bitrate :波特率
  * @retval 预分频系数
  */
uint16_t brp_from_birate_48(uint32_t bitrate)
{
    if(bitrate == 10000)
        return 300;
    if(bitrate == 50000)
        return 60;
    if(bitrate == 125000)
        return 24;
    if(bitrate == 250000)
        return 12;
    if(bitrate == 500000)
        return 6;
    if(bitrate == 1000000)
        return 6;
    return 60;
}

/**
  * @brief  基于24M系统时钟及选择波特率，计算CAN时钟的预分频系数
  * @param  bitrate :波特率
  * @retval 预分频系数
  */
uint16_t brp_from_birate_24(uint32_t bitrate)
{
    if(bitrate == 10000)
        return 150;
    if(bitrate == 50000)
        return 30;
    if(bitrate == 125000)
        return 12;
    if(bitrate == 250000)
        return 6;
    if(bitrate == 500000)
        return 3;
    if(bitrate == 1000000)
        return 3;
    return 30;
}

/**
  * @brief:CAN处理器初始化
  * @param  bitrate :波特率
  * @retval
  * NOTE: 如下是当前系统时钟配置，由于CAN处理器挂接到APB1总线上，而且APB1预分频系统数为1，所以
  * CAN总线的输入时钟频率为48M.不过最终的输入时钟要取决于CAN处理的分频系数。后面有提到
  *=============================================================================
  *        System Clock source          | PLL(HSE)
  *-----------------------------------------------------------------------------
  *        SYSCLK                       | 48000000 Hz
  *-----------------------------------------------------------------------------
  *        HCLK                         | 48000000 Hz
  *-----------------------------------------------------------------------------
  *        AHB Prescaler                | 1
  *-----------------------------------------------------------------------------
  *        APB1 Prescaler               | 1
  *-----------------------------------------------------------------------------
  *        APB2 Prescaler               | 1
  *-----------------------------------------------------------------------------
  *        HSE Frequency                | 8000000 H
  * */
void can_init(uint32_t bitrate)
{
  GPIO_InitTypeDef  GPIO_InitStructure;
  NVIC_InitTypeDef  NVIC_InitStructure;
  CAN_InitTypeDef        CAN_InitStructure;
  CAN_FilterInitTypeDef  CAN_FilterInitStructure;
  uint8_t ret = 0;

  /* Enable GPIO clock */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
  /* Enable CAN clock */
  //CAN总线挂在到APB1，所以总线APB1时钟即为CAN时钟，
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);
  //==============特别注意==========================
  //由于CAN总线的IO和串口等外设是公用的，所以需要进行端口映射
  //为此可以使用下面的方法，进行端口映射。将PA11和PA12端口，映射成CAN功能
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
  SYSCFG->CFGR1 = SYSCFG->CFGR1 | SYSCFG_CFGR1_PA11_PA12_RMP;

  /* Connect CAN pins to AF7 */
  /* CAN GPIOs configuration **************************************************/
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_4); //选择CAN功能，开发时具体要查一下datasheet.
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_4); //选择CAN功能，开发时具体要查一下datasheet

  /* Configure CAN RX and TX pins */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* CAN configuration ********************************************************/

  /* CAN register init */
  CAN_DeInit(CAN);
  CAN_StructInit(&CAN_InitStructure);

  /* CAN cell init */
  CAN_InitStructure.CAN_TTCM = DISABLE;     //非时间触发通信模式
  CAN_InitStructure.CAN_ABOM = ENABLE;      //软件自动离线管理
  CAN_InitStructure.CAN_AWUM = ENABLE;      //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
  CAN_InitStructure.CAN_NART = DISABLE;     //禁止报文自动传送
  CAN_InitStructure.CAN_RFLM = ENABLE;      //报文不锁定,新的覆盖旧的
  CAN_InitStructure.CAN_TXFP = DISABLE;     //优先级由报文标识符决定
  CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
  //CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack;

  /* CAN Baudrate (CAN clocked at 48 MHz)  48e6 / ( prescaler * (1+BS1+BS2))  */
  CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
  if(bitrate == 1000000){
    CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq;
    CAN_InitStructure.CAN_BS2 = CAN_BS2_1tq;
  }
  else{
    CAN_InitStructure.CAN_BS1 = CAN_BS1_13tq;
    CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
  }
  if(SystemCoreClock == 24000000)
    CAN_InitStructure.CAN_Prescaler = brp_from_birate_24(bitrate);
  else
    //CAN_InitStructure.CAN_Prescaler = 5;
    CAN_InitStructure.CAN_Prescaler = brp_from_birate_48(bitrate);

  ret = CAN_Init(CAN, &CAN_InitStructure);
  SYS_DEBUG(("bitrate:%d,ret:%d",bitrate,ret));

  /* CAN filter init */
  CAN_FilterInitStructure.CAN_FilterNumber = 0;
  CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
  //CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
  CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_16bit;
  CAN_FilterInitStructure.CAN_FilterIdHigh = (u16)0x110 << 5;
  CAN_FilterInitStructure.CAN_FilterIdLow = (u16)0x111 << 5;
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh = (u16)0x112 << 5;
  CAN_FilterInitStructure.CAN_FilterMaskIdLow = (u16)0x113 << 5;
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;
  CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
  CAN_FilterInit(&CAN_FilterInitStructure);
  /* Transmit Structure preparation */

  /* Enable FIFO 0 message pending Interrupt */
  CAN_ITConfig(CAN, CAN_IT_FMP0, ENABLE);
  CAN_ITConfig(CAN, CAN_IT_FF0, ENABLE);

  /* NVIC configuration *******************************************************/
  NVIC_InitStructure.NVIC_IRQChannel = CEC_CAN_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

void Can_Erros_status(u32 reg_val)
{
    SYS_DEBUG(("reciive error counter->REC:%d",(reg_val >> 24)&0xff));
    SYS_DEBUG(("transmit error counter->TEC:%d",(reg_val >> 16)&0xff));
    SYS_DEBUG(("last error code->LEC:%s",can_err_str[(reg_val >> 4)&0x07]));
    SYS_DEBUG(("Bus-off flag->BOFF:0x%x",(reg_val >> 2)&0x01));
    SYS_DEBUG(("Error passive flag->EPVF:0x%x",(reg_val >> 1)&0x01));
    SYS_DEBUG(("Error warning flag->EWGF:0x%x",reg_val&0x01));

    SYS_DEBUG(("can:MSR:0x%x",CAN->MSR));
    SYS_DEBUG(("can:IER:0x%x",CAN->IER));
}
void CEC_CAN_IRQHandler(void)
{
    int i;
    uint8_t rbuf[10];
    CanRxMsg RxMessage = {0};
    SYS_DEBUG(("rece_data!"));
    if(CAN_GetITStatus(CAN, CAN_IT_FMP0) == SET){
        //CAN_ClearITPendingBit(CAN, CAN_IT_FMP0);
        CAN_Receive(CAN, CAN_FIFO0, &RxMessage);
        SYS_DEBUG(("msg.len:%d",RxMessage.DLC));
        // Drop extended frames
        for(i=0;i<RxMessage.DLC;i++)
            rbuf[i]=RxMessage.Data[i];
        SYS_DEBUG(("rec:%s",rbuf));
    }
}
